<?php

class FolderController extends Controller
{
	public $defaultAction='admin';
	/**
	 * @return array action filters
	 */
	public function filters()
	{
		return array(
			'accessControl', // perform access control for CRUD operations
		);
	}

	/**
	 * Specifies the access control rules.
	 * This method is used by the 'accessControl' filter.
	 * @return array access control rules
	 */
	public function accessRules()
	{
		return CMap::mergeArray(array(
        	array('allow',
            	'actions'=>array('admin','view', 'svnUp', 'SvnStatus', 'SvnSwitchToSelf', 'svnRevert', 'svnShowInfo', 'svnShowLog', 'svnUpToRevision'),
            	'expression'=>array($this, 'checkOwnership'),
                #'roles'=>array('DEVELOPER'),
        	),
		), parent::accessRules());
	}

	function checkOwnership(HqUserComponent $user, CAccessRule $rule)
	{
        if (!$user->hasRole('DEVELOPER')) return !$rule->allow;
        if (!isset($_GET['id']) || empty($_GET['id'])) return $rule->allow;

        $u = OpenIdUser::model()->findByAttributes(array('email'=>$user->email));

        $x = DeveloperFolder::model()->findByAttributes(array(
        	'folder_id'=>$_GET['id'],
        	'user_id'=>$u->id
        ));

        return !empty($x) && $rule->allow;
	}

	protected function runCommand($cmd)
	{
        $outfile = tempnam(".", "cmd");
	    $errfile = tempnam(".", "cmd");
	    $descriptorspec = array(
	        0 => array("pipe", "r"),
	        1 => array("file", $outfile, "w"),
	        2 => array("file", $errfile, "w")
	    );

	    $pipes = array();

	    $proc = proc_open($cmd, $descriptorspec, $pipes);
	    assert('$proc !== false');

	    fclose($pipes[0]);    //Don't really want to give any input

	    $exit = proc_close($proc);
	    $stdout = file($outfile);
	    $stderr = file($errfile);

	    unlink($errfile);
	    unlink($outfile);

	    return array($exit, $stdout, $stderr);
	}

	protected function runSVNCommand(Folder $folder, $command)
	{
		$userModel = OpenIdUser::model()->findByAttributes(array('email'=>Yii::app()->user->email));
		$svnCommand = Yii::app()->registry->svnCommand;

		$paths = explode("\n",$folder->path);
		$output = '';

		$logs = array();

		$returnVar = 0;
		$rv = 0;
		foreach($paths as $key => $path){
			$path = trim($path, " \r\n");
			if (empty($path)) continue;
			if ($path[0] == '#') continue;
			$cmd = $svnCommand . ' ' . strtr($command, array(':path'=>escapeshellarg($path)));
			Yii::log($cmd, CLogger::LEVEL_TRACE, 'app');
			list($rv, $stdout, $stderr) = $this->runCommand($cmd);

            $logs[] = array(
            	'cmd'=>$cmd,
            	'path'=>$path,
            	'return'=>$rv,
            	'stdout'=>$stdout,
            	'stderr'=>$stderr,
            );

            $logStr = implode("\n", $stderr)."\n--SEPARATOR BETWEEN STDERR & STDOUT--\n".implode("\n", $stdout);
			$this->writeLog($cmd, $userModel->id, $folder->id, $path, $logStr);
		}
		return $logs;
	}

	function checkFolderUser($user, $role)
	{
		$folder_id = isset($_GET['folder_id'])?$_GET['folder_id']:$_GET['id'];
		if(isset ($user->id)){
			$x = OpenIdUser::model()->findByAttributes(array('email'=>$user->email));
			$developer_folder = DeveloperFolder::model()->findAll('user_id = :user_id
				AND folder_id = :folder_id', array(
				':user_id' => $x->id,
				':folder_id' => $folder_id,
				)
			);
			return (!empty($developer_folder));
		}

		return false;
	}

	public function allowCustomerCareOnly(CWebUser $user, CAccessRule $rule)
	{
		if ($user->isGuest) return !$rule->allow;
		$x = OpenIdUser::model()->findByAttributes(array('email'=>$user->email));

		$allow = !is_null($x) && in_array('DEVELOPER', $x->roles);
		if ($allow) return $rule->allow;
		else return !$rule->allow;
	}

	/**
	 * Displays a particular model.
	 * @param integer $id the ID of the model to be displayed
	 */
	public function actionView($id)
	{
        if (isset($_POST['btnUpdate'])) return $this->run('svnUp');
        if (isset($_POST['btnUpdate2Rev'])) return $this->run('svnUpToRevision');
        if (isset($_POST['btnShowlog'])) return $this->run('svnShowLog');
        if (isset($_POST['btnInfo'])) return $this->run('svnShowInfo');
        if (isset($_POST['btnStatus'])) return $this->run('svnStatus');
        if (isset($_POST['btnRevert'])) return $this->run('svnRevert');
        if (isset($_POST['btnSwitchToSelf'])) return $this->run('svnSwitchToSelf');

		$this->render('view',array(
			'model'=>$this->loadModel($id),
			'logs'=>array(),
		));
	}

	/**
	 * Creates a new model.
	 * If creation is successful, the browser will be redirected to the 'view' page.
	 */
	public function actionCreate()
	{
		$model=new Folder;

		// Uncomment the following line if AJAX validation is needed
		// $this->performAjaxValidation($model);

		if(isset($_POST['Folder']))
		{
			$model->attributes=$_POST['Folder'];
			if($model->save())
				$this->redirect(array('view','id'=>$model->id));
		}

		$this->render('create',array(
			'model'=>$model,
		));
	}


	/**
	 * Updates a particular model.
	 * If update is successful, the browser will be redirected to the 'view' page.
	 * @param integer $id the ID of the model to be updated
	 */
	public function actionUpdate($id)
	{
		$model=$this->loadModel($id);

		if(isset($_POST['Folder']))
		{
			$model->attributes=$_POST['Folder'];
			if($model->save())
				$this->redirect(array('view','id'=>$model->id));
		}

		$this->render('update',array(
			'model'=>$model,
		));
	}

	/**
	 * Deletes a particular model.
	 * If deletion is successful, the browser will be redirected to the 'admin' page.
	 * @param integer $id the ID of the model to be deleted
	 */
	public function actionDelete($id)
	{
		if(Yii::app()->request->isPostRequest)
		{
			// we only allow deletion via POST request
			$this->loadModel($id)->delete();

			// if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
			if(!isset($_GET['ajax']))
				$this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
		}
		else
			throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');
	}

	/**
	 * Lists all models.
	 */
	public function actionIndex()
	{
		$user = Yii::app()->user;
		$x = OpenIdUser::model()->findByAttributes(array('email'=>$user->email));

		if(in_array('ADMIN', $x->roles)){
		 	$dataProvider=new CActiveDataProvider('Folder');
			$this->render('index',array(
				'dataProvider'=>$dataProvider,
			));
		}else if(in_array('DEVELOPER', $x->roles)){
			$criteria=new CDbCriteria;
			$criteria->join ='JOIN developer_folder on t.id = developer_folder.folder_id';
			$criteria->addCondition('developer_folder.user_id = '.$x->id);
			$dataProvider=new CActiveDataProvider('Folder',array(
				'criteria'=>$criteria,
			));
			$this->render('index',array(
				'dataProvider'=>$dataProvider,
			));
		}
	}

	/**
	 * Manages all models.
	 */
	public function actionAdmin()
	{
		$model=new Folder('search');
		$model->unsetAttributes();  // clear any default values
		if(isset($_GET['Folder']))
		$model->attributes=$_GET['Folder'];

		$user = Yii::app()->user;
		$x = OpenIdUser::model()->findByAttributes(array('email'=>$user->email));

		if(in_array('ADMIN', $x->roles))
			return $this->render('admin',array(
				'model'=>$model,
			));

		if(in_array('DEVELOPER', $x->roles))
			$this->render('user_manage',array(
				'model'=>$model,
				'user_id' => $x->id,
			));
	}

	public function actionSetUserRole($folder_id)
	{
		$folderModel = $this->loadModel($folder_id);
		$c = new CDbCriteria();
		$c->compare('roles', 'DEVELOPER', true);
		$users = OpenIdUser::model()->findAll($c);
		$user_ids = DeveloperFolder::model()->getUserIdsByFolderId($folder_id);
		if(isset($_POST['submit'])){
			DeveloperFolder::model()->deleteAll('folder_id = '.$folder_id);
			if(isset($_POST['user'])){
				$user_ids = $_POST['user'];
				DeveloperFolder::model()->insertRecordByuserIds($folder_id,$user_ids);
				Yii::app()->user->setFlash('success', 'Update successfully.');
			}
		}

		$this->render(
			'setUserRole',
			array(
				'model' => $folderModel,
				'users'	=> $users,
				'user_ids' => $user_ids,
			)
		);
	}

	/**
	 * Returns the data model based on the primary key given in the GET variable.
	 * If the data model is not found, an HTTP exception will be raised.
	 * @param integer the ID of the model to be loaded
	 */
	public function loadModel($id)
	{
		$model=Folder::model()->findByPk($id);
		if($model===null)
			throw new CHttpException(404,'The requested page does not exist.');
		return $model;
	}

	/**
	 * Performs the AJAX validation.
	 * @param CModel the model to be validated
	 */
	protected function performAjaxValidation($model)
	{
		if(isset($_POST['ajax']) && $_POST['ajax']==='folder-form')
		{
			echo CActiveForm::validate($model);
			Yii::app()->end();
		}
	}

	public function actionSvnUpToRevision($id)
	{
		$model = $this->loadModel($id);
		$rev = isset($_POST['rev']) ? $_POST['rev'] : 'HEAD';
		if (empty($rev)) $rev = 'HEAD';

		$rev = escapeshellarg($rev);

		$logs = $this->runSVNCommand(
			$model,
			"update :path -r{$rev}"
		);

        $this->render('view',array(
			'model'=>$model,
			'logs'=>$logs,
		));
	}

	public function actionSvnUp($id)
	{
		$model = $this->loadModel($id);

		$logs = $this->runSVNCommand(
			$model,
			"update :path"
		);

		$this->render('view',array(
			'model'=>$model,
			'logs'=>$logs,
		));
	}
	 
	public function actionSvnSwitchToSelf($id)
	{
		$model = $this->loadModel($id);
		$logs = $this->runSVNCommand(
			$model,
			"switch $model->svn_url :path"
		);
		$this->render('view',array(
			'model'=>$model,
			'logs'=>$logs,
		));
	}

	public function actionSvnRevert($id)
	{
		$model = $this->loadModel($id);

		$logs = $this->runSVNCommand(
			$model,
			"revert * -R :path"
		);

		$this->render('view',array(
			'model'=>$model,
			'logs'=>$logs,
		));
	}

	public function actionSvnStatus($id)
	{
		$model = $this->loadModel($id);

		$logs = $this->runSVNCommand(
			$model,
			"status :path"
		);

		$this->render('view',array(
			'model'=>$model,
			'logs'=>$logs,
		));
	}

	public function actionSvnShowLog($id)
	{
		$model = $this->loadModel($id);
		$logs = $this->runSVNCommand(
			$model,
			"log -v :path"
		);
       
		$this->render('view',array(
			'model'=>$model,
			'logs'=>$logs,
		));
	}

	public function actionSvnShowInfo($id)
	{
		$model = $this->loadModel($id);

		$logs = $this->runSVNCommand(
			$model,
			"info :path"
		);

		$this->render('view',array(
			'model'=>$model,
			'logs'=>$logs,
		));
	}

	public function writeLog($action,$user_id,$folder_id,$path,$output)
	{
		$model=new Log();
		$attributes = array();
		$attributes['action'] = $action;
		$attributes['user_id'] = $user_id;
		$attributes['folder_id'] = $folder_id;
		$attributes['path'] = $path;
		$attributes['output'] = $output;
		$attributes['time'] = date('o-m-d H:i:s',time());
		$model->attributes=$attributes;
		$model->save();
	}

	public function checkAdmin()
	{
		$user = Yii::app()->user;
		if(!empty($user->email)){
			$x = OpenIdUser::model()->findByAttributes(array('email'=>$user->email));
			if(in_array('ADMIN', $x->roles)){
			return true;
			}
		}
		return false;
	}

}
